/* eslint-disable no-unused-expressions */
/* eslint-disable no-nested-ternary */
import React, {
  useMemo,
  useCallback,
  useState,
  useRef,
  useEffect,
  forwardRef,
  useImperativeHandle,
} from "react";
import { Tag } from "choerodon-ui";
import { Form, Output, DataSet } from "choerodon-ui/pro";
import { notification, message, Dropdown, Menu, Tooltip, Spin } from "hzero-ui";
import styled from "styled-components";
import { isNil, isPlainObject, isArray, isNumber, sortBy } from "lodash";
import moment from "moment";
import "dhtmlx-gantt/codebase/dhtmlxgantt.css";
import GanttChart from "tms-front/lib/components/GanttChart";

import request from "utils/request";
import { HCES_HTMS } from "tmsCommon/config";

import { getCurrentOrganizationId } from "utils/utils";

import MacroNotification from "tms-front/lib/common/htms/components/MacroNotification";

// import beforeDayPNG from "./assets/before-day.png";
// import afterDayPNG from "./assets/after-day.png";

const beforeDayPNG =
  "https://handtms-static.obs.cn-east-3.myhuaweicloud.com/component/0/8a5c2baf9cab4570943971fe9536d123%40before-day.png";
const afterDayPNG =
  "https://handtms-static.obs.cn-east-3.myhuaweicloud.com/component/0/12329da91da140818e857119b06ce420%40after-day.png";

const currentTenantID = getCurrentOrganizationId();

function macroRequest(params): Promise<any> {
  return request(`${HCES_HTMS}/v1/${currentTenantID}/tp/macro/excuteMacro`, {
    body: params,
    method: "POST",
  });
}

//**************************************MinuteStep组件************************************************ */
const { Item } = Menu;

type MinuteStepProps = {
  minuteStep: number;
  setMinuteStep: (step: number, cb: Function) => void;
  updateGanttLayout: () => void;
};

function MinuteStep(props: MinuteStepProps) {
  const { minuteStep, setMinuteStep, updateGanttLayout } = props;

  const handleItemClick = useCallback((step: number) => {
    setMinuteStep(step, () => {
      updateGanttLayout();
    });
  }, []);

  const menu = useMemo(() => {
    const items: number[] = [10, 12, 15, 20, 30];
    return (
      <Menu>
        {items.map((item) => (
          <Item
            style={{ padding: "0 8px" }}
            onClick={() => handleItemClick(item)}
          >
            {item}
          </Item>
        ))}
      </Menu>
    );
  }, []);

  return (
    <>
      <Dropdown overlay={menu} placement='bottomRight'>
        <div style={{ float: "right", padding: "0 10px", cursor: "pointer" }}>
          {minuteStep} 分钟/格
        </div>
      </Dropdown>
    </>
  );
}

//**************************************RailwayGantt组件************************************************ */

const Space = styled.div`
  margin-top: 20px;
`;

const GanttDayHeader = styled.div`
  background: transparent;
  height: 25px;
  margin-bottom: -25px;
  position: relative;
  top: 0;
  left: 0;
  z-index: 999;
  float: right;
  width: calc(100% - 300px);
  text-align: center;
  line-height: 25px;
  color: #a6a6a6;

  img {
    width: 14px;
    margin-top: -2px;
    cursor: pointer;
  }

  .before-day {
    margin-right: 6px;
  }

  .after-day {
    margin-left: 6px;
  }
`;

const GanttContainer = styled.div`
  height: 292px;
  user-select: none;

  .gantt-grid-head-cell {
    border-right: 1px solid #ebebeb !important;
  }

  .enable-task {
    background: #2c6ffe;
    border: 2px solid #2c6ffe;

    :global {
      .gantt_task_content {
        text-overflow: ellipsis;
      }
    }
  }

  .disable-task {
    background: #6b6b6b;
    border: 2px solid #6b6b6b;

    &:hover {
      cursor: not-allowed;
    }

    :global {
      .gantt_task_content {
        cursor: not-allowed;
        text-overflow: ellipsis;
      }
    }
  }

  .selected-task {
    border: 2px solid #07e2f3;
    background: #0ebdef;
  }
`;

const RailwayGantt = forwardRef(
  (
    props: {
      minuteStep: any;
      setMinuteStep: any;
      setSelectedTask: any;
      queryGanttData: any;
      data: any;
    },
    ref,
  ) => {
    const container = useRef(null);
    const GanttXRef = useRef(0);
    const [ganttDateValue, setGanttDateValue] = useState(
      new Date(moment().format("YYYY-MM-DD 00:00:00")).valueOf(),
    );

    const { minuteStep, setMinuteStep, data, queryGanttData } = props;
    // HTMSGanttChartFactory为甘特图组件暴露的方法
    const gantt = useMemo(() => HTMSGanttChartFactory().gantt, []);

    useEffect(() => {
      initGannt();
    }, [gantt, container]);

    useEffect(() => {
      updateGantt();
    }, [data]);

    useEffect(() => {
      updateGanttLayout();
    }, [minuteStep]);

    useEffect(() => {
      gantt.config.start_date = new Date(
        moment(ganttDateValue).format("YYYY-MM-DD 00:00:00"),
      );
      gantt.config.end_date = new Date(
        moment(ganttDateValue).format("YYYY-MM-DD 23:59:59"),
      );
      queryGanttData?.();
    }, [ganttDateValue]);

    const initGannt = () => {
      if (!container?.current) return;
      if (!gantt) return;

      gantt.plugins({
        tooltip: true,
      });
      gantt.config.columns = [
        {
          name: "locationName",
          label: "仓库名称",
          tree: false,
          align: "center",
          resize: true,
          width: 150,
        },
        {
          name: "dockName",
          label: "月台名称",
          tree: false,
          align: "center",
          resize: true,
          width: 150,
        },
      ];
      gantt.templates.grid_header_class = (columnName) => {
        if (columnName === "locationName") {
          return "gantt-grid-head-cell";
        }
      };
      setGanttScales();
      gantt.config.scale_height = 75;
      gantt.config.min_column_width = 20;
      gantt.config.readonly = true;
      gantt.config.date_format = "%Y-%m-%d %H:%i";
      gantt.config.duration_unit = "minute";
      gantt.config.duration_step = 1;
      gantt.config.row_height = 40;
      gantt.config.task_height = 30;
      gantt.templates.task_class = (start, end, task) => {
        const { enable, isSelected } = task;

        return enable
          ? isSelected
            ? "enable-task selected-task"
            : "enable-task"
          : "disable-task";
      };
      gantt.templates.task_text = (start, end, task) => {
        const { enable, dimension, count, parentEnable, name } = task;
        return !parentEnable
          ? "不可用"
          : enable
          ? `${name ? name + " | " : ""}可预约${
              isNil(dimension) ? "-" : dimension
            }：${isNil(count) ? "-" : count}`
          : "已约满";
      };
      gantt.templates.tooltip_text = (start, end, task) => {
        const { $level, enable, dimension, count, parentEnable, name } = task;

        if ($level !== 0) {
          return `<div style="background:black;
          color:white;
          padding:6px;
          margin:-11px;
          border: 1px solid black;
          opacity: 0.8;">
            ${
              !parentEnable
                ? "不可用"
                : enable
                ? `${name ? name + " | " : ""}可预约${
                    isNil(dimension) ? "-" : dimension
                  }：${isNil(count) ? "-" : count}`
                : "已约满"
            }
          </div>`;
        }
      };
      gantt.attachEvent("onTaskUnselected", (id) => {
        if (gantt.isTaskExists(id)) {
          const task = gantt.getTask(id);
          const { enable, $level } = task;
          if ($level !== 0 && enable) {
            task.isSelected = false;
            gantt.updateTask(id);
          }
        }
      });
      gantt.attachEvent("onTaskClick", (id) => {
        const task = gantt.getTask(id);
        const { enable, $level, isSelected } = task;
        if ($level !== 0 && enable) {
          const { setSelectedTask } = props;
          if (isSelected) {
            task.isSelected = false;
            setSelectedTask?.(null);
            notification.info({
              description: "",
              message: "时间窗已取消。",
            });
          } else {
            task.isSelected = true;
            setSelectedTask?.(task);
            notification.info({
              description: "",
              message: "时间窗已选中。",
            });
          }
          gantt.updateTask(id);
        }
        return $level !== 0 && enable;
      });
      gantt.attachEvent("onGanttReady", () => {
        const { tooltips } = gantt.ext;
        tooltips.tooltip.setViewport(gantt.$task_data);
        gantt.scrollTo(0, 0);
      });
      // 初始化
      gantt.init(
        container.current,
        new Date(moment().format("YYYY-MM-DD 00:00:00")),
        new Date(moment().format("YYYY-MM-DD 23:59:59")),
      );
      gantt.parse({
        data: props.data,
      });
    };

    const setGanttScales = () => {
      const { minuteStep } = props;
      gantt.config.scales = [
        {
          unit: "day",
          format: formatHeader,
        },
        {
          unit: "hour",
          format: "%G %a",
        },
        {
          unit: "minute",
          step: minuteStep,
          format: "%i",
        },
      ];
    };

    const formatHeader = () => {
      return "";
    };

    const title = moment(ganttDateValue).format("MM/DD/YYYY");

    const updateGantt = () => {
      const { data, setSelectedTask } = props;
      const x = GanttXRef.current;
      setSelectedTask(null);
      gantt.clearAll();
      gantt.parse({ data });
      gantt.scrollTo(x, 0);
    };

    const getGanttDate = () => {
      return moment(ganttDateValue).format("YYYY-MM-DD");
    };

    const updateGanttX = (x) => {
      GanttXRef.current = x;
    };

    const updateGanttLayout = () => {
      setGanttScales();
      gantt.render();
    };

    const handleBeforeDay = () => {
      const day = 24 * 60 * 60 * 1000;
      setGanttDateValue(ganttDateValue - day);
    };

    const handleAfterDay = () => {
      const day = 24 * 60 * 60 * 1000;
      setGanttDateValue(ganttDateValue + day);
    };

    useImperativeHandle(ref, () => ({
      gantt,
      getGanttDate,
      updateGanttX,
    }));

    return (
      <>
        {/* <div className={styles.space} /> */}
        <Space />
        <GanttDayHeader>
          <img
            src={beforeDayPNG}
            alt='前一天'
            className='before-day'
            onClick={() => handleBeforeDay()}
          />
          {title}
          <img
            src={afterDayPNG}
            alt='后一天'
            className='after-day'
            onClick={() => handleAfterDay()}
          />
          <MinuteStep
            minuteStep={minuteStep}
            setMinuteStep={setMinuteStep}
            updateGanttLayout={() => {
              console.log("更新甘特图");
            }}
          />
        </GanttDayHeader>
        <GanttContainer ref={container} onMouseLeave={() => {}} />
      </>
    );
  },
);

// const data = [
//   {
//     id: "1",
//     render: "split",
//     start_date: "2022-12-16 00:00",
//     end_date: "2022-12-16 00:00",
//     duration: 0,
//     isSelected: false,
//     locationName: "北京仓库RDC",
//     locationGid: 59500,
//     dockName: "北京仓库月台A",
//     dockGid: 4,
//     enable: true,
//   },
//   {
//     parent: "1",
//     id: "1.1",
//     dimension: "重量",
//     count: 1000,
//     locationGid: 59500,
//     dockGid: 4,
//     dockResourceLineGid: 2,
//     isSelected: false,
//     parentEnable: true,
//     enable: true,
//     start_date: "2022-12-16 13:00",
//     end_date: "2022-12-16 19:00",
//     appointmentDate: "2022-12-16 00:00:00",
//   },
//   {
//     parent: "1",
//     id: "1.2",
//     dimension: "重量",
//     count: 1000,
//     locationGid: 59500,
//     dockGid: 4,
//     dockResourceLineGid: 1,
//     isSelected: false,
//     parentEnable: true,
//     enable: true,
//     start_date: "2022-12-16 08:00",
//     end_date: "2022-12-16 12:00",
//     appointmentDate: "2022-12-16 00:00:00",
//   },
// ];
//**************************************单元测试************************************************ */

// 测试 MinuteStep 组件
// const App = () => {
//   const [minuteStep, setMinuteStep] = useState(10);

//   return (
//     <>
//       <MinuteStep
//         minuteStep={minuteStep}
//         setMinuteStep={setMinuteStep}
//         updateGanttLayout={() => {
//           console.log("更新甘特图");
//         }}
//       />
//     </>
//   );
// };

// 测试 RailwayGantt组件

// const App = () => {
//   const [minuteStep, setMinuteStep] = useState(10);

//   return (
//     <>
//       <RailwayGantt
//         minuteStep={minuteStep}
//         setMinuteStep={setMinuteStep}
//         setSelectedTask={() => {
//           console.log("选择任务");
//         }}
//         data={data}
//       />
//     </>
//   );
// };

//**************************************工具方法************************************************ */

function queryGantt(param) {
  return request(
    // http://localhost:9080/v1/2/htms/shipment/stop/query-platform-reservation?ganttDate=2022-12-19 00:00:00&id=34636&locationGid=59500
    `${HCES_HTMS}/v1/${currentTenantID}/htms/shipment/stop/query-platform-reservation`,
    {
      method: "GET",
      query: param,
    },
  );
}

function handleSlideWindow(day, second) {
  let baseValue = new Date(`${day} 00:00:00`).valueOf();
  let value = 0;
  try {
    const digit = Number(second);
    if (isNumber(digit)) {
      value = digit * 1000;
    }
  } finally {
    baseValue += value;
  }
  return moment(baseValue).format("YYYY-MM-DD HH:mm");
}

function handleGanttDataReceive(data, day, extraData) {
  const { stopType } = extraData;
  const ganttData = [];
  if (isPlainObject(data)) {
    const { docks } = data;
    if (isArray(docks)) {
      // 遍历月台
      for (let i = 0; i < docks.length; i++) {
        const dock = docks[i];
        if (isPlainObject(dock)) {
          const row = {};
          const {
            locationName,
            locationGid,
            name: dockName,
            id: dockGid,
            dockResourceLineList,
            appointmentActivityType,
          } = dock;
          row.id = `${i + 1}`;
          row.render = "split";
          row.start_date = moment(`${day} 00:00:00`).format("YYYY-MM-DD HH:mm");
          row.end_date = moment(`${day} 00:00:00`).format("YYYY-MM-DD HH:mm");
          row.duration = 0;
          row.isSelected = false;
          row.locationName = locationName;
          row.locationGid = locationGid;
          row.dockName = dockName;
          row.dockGid = dockGid;
          row.enable =
            appointmentActivityType === "PD"
              ? true
              : appointmentActivityType === stopType;
          ganttData.push(row);
          if (isArray(dockResourceLineList)) {
            // 遍历时间窗
            for (let j = 0; j < dockResourceLineList.length; j++) {
              const slideWindow = dockResourceLineList[j];
              if (isPlainObject(slideWindow)) {
                const item = {};
                const {
                  dimension,
                  remainingCapacity,
                  id: dockResourceLineGid,
                  name,
                  fromSlot,
                  toSlot,
                } = slideWindow;
                item.parent = `${i + 1}`;
                item.id = `${i + 1}.${j + 1}`;
                item.dimension = dimension;
                item.count = isNumber(remainingCapacity)
                  ? remainingCapacity
                  : 0;
                item.locationGid = locationGid;
                item.name = name;
                item.dockGid = dockGid;
                item.dockResourceLineGid = dockResourceLineGid;
                item.isSelected = false;
                item.parentEnable = row.enable;
                item.enable = row.enable && item.count > 0;
                item.start_date = handleSlideWindow(day, fromSlot);
                item.end_date = handleSlideWindow(day, toSlot);
                item.appointmentDate = `${day} 00:00:00`;
                ganttData.push(item);
              }
            }
          }
        }
      }
    }
  }
  return ganttData;
}

function findX(data, minuteStep = 10) {
  let x = 0;
  const times = [];
  if (isPlainObject(data)) {
    const { docks } = data;
    if (isArray(docks)) {
      for (let i = 0; i < docks.length; i++) {
        const dock = docks[i];
        if (isPlainObject(dock)) {
          const { dockResourceLineList } = dock;
          if (isArray(dockResourceLineList)) {
            for (let j = 0; j < dockResourceLineList.length; j++) {
              const win = dockResourceLineList[j];
              if (isPlainObject(win)) {
                const { fromSlot } = win;
                let fromTimeValue = 0;
                if (!isNil(fromSlot) && !isNaN(Number(fromSlot))) {
                  fromTimeValue = Number(fromSlot);
                }
                times.push(fromTimeValue);
              }
            }
          }
        }
      }
    }
  }
  const newTimes = sortBy(times);
  if (newTimes.length) {
    x = newTimes[0];
  }
  const minWid = 20;
  x = parseInt((x / 60 / minuteStep) * minWid, 10);
  return x;
}

//**************************************普通组件************************************************ */
const ContentWrapper = styled.div`
  position: relative;
  width: ${(props) => (props.width ? props.width : "650px")};
  padding-bottom: 60px;
`;

const Footer = styled.div`
  position: absolute;
  bottom: 0;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  width: 100%;
  height: 50px;
  border-top: 0.01rem solid #e0e0e0;
  background-color: #fff;

  .button {
    display: flex;
    flex: none;
    align-items: center;
    justify-content: content;
    height: 28px;
    padding: 0px 12px;
    border-radius: 2px;
    cursor: pointer;
    transition: 0.3s;
    user-select: none;
  }

  .cancel {
    color: #000000d9;
    background-color: #fff;
    border: 1px solid #e6e6e6;

    &:hover {
      border-color: #29becf;
      color: #29becf;
      background-color: #fff;
    }

    &:active {
      border-color: #1995a8;
      color: #1995a8;
      background-color: #fff;
    }
  }

  .confirm {
    margin-left: 10px;
    margin-right: 15px;
    color: #fff;
    background-color: #29becf;
    border-color: #29becf;
    cursor: pointer;

    &:hover {
      color: #ffffff;
      background-color: #79e4e8;
      border-color: #79e4e8;
    }

    &:active {
      color: #fff;
      background-color: #1995a8;
      border-color: #1995a8;
    }
  }
`;
const MainInfo = styled.div`
  .main-title {
    display: flex;
    .main-tag {
      font-weight: bold;
      font-size: 14px;
      flex: none;
      white-space: nowrap;
      margin-right: 20px;
    }
  }
`;

//**************************************业务组件************************************************ */

const stopDs = () => {
  return {
    fields: [
      {
        name: "locationName",
        label: "仓库名称",
      },
      {
        name: "plannedArrival",
        label: "计划到达时间",
      },
      {
        name: "totalItemCount",
        label: "总数量",
      },
      {
        name: "totalWeight",
        label: "总重量",
      },
      {
        name: "totalVolume",
        label: "总体积",
      },
      {
        name: "stopType",
        lookupCode: "HTMS.ROUTE_STOP_TYPE",
      },
    ],
  };
};

const App = (props) => {
  const { record } = props;

  const [minuteStep, setMinuteStep] = useState(10);

  const [ganttData, setGanntData] = useState([]);
  const [stopType, setStopType] = useState("");

  const [selectedTask, setSelectedTask] = useState(null);

  const ganntRef = useRef();

  const formDs = useMemo(() => {
    const dataSet = new DataSet(stopDs());
    const { record } = props;
    dataSet.loadData([record]);
    return dataSet;
  }, []);

  useEffect(() => {
    (async () => {
      await queryGanttData();
    })();
  }, [ganntRef]);

  useEffect(() => {
    (async () => {
      const field = formDs.getField("stopType");
      if (!field) return;
      await field.fetchLookup(false).catch(console.error);
      const { record } = props;
      const stopType = field.getText(record.stopType);
      setStopType(stopType);
    })();
  }, [formDs]);

  const queryGanttData = async () => {
    const { record } = props;
    const ganntInstance = ganntRef.current;

    if (!ganntInstance) return;

    const { locationGid, id } = record;

    const ganntDate = ganntInstance?.getGanttDate();

    const param = {
      locationGid,
      ganttDate: `${ganntDate} 00:00:00`,
      id,
    };
    const response = await queryGantt(param);

    if (!response) return;

    const { success, data, message } = response;

    if (!success) {
      notification.error({
        message: message || "操作失败",
      });

      setGanntData([]);
      ganntInstance?.updateGanttX(0);
    }

    const ganttData = handleGanttDataReceive(data, ganntDate, record);
    const x = findX(data, minuteStep);
    setGanntData(ganttData);
    ganntInstance?.updateGanttX(x);
  };

  const cancel = () => {
    const { targetModal } = props;
    targetModal.close();
  };

  const confirm = async () => {
    // do something
    if (!selectedTask) {
      notification.error({
        description: "",
        message: "请选择时间窗",
      });

      return;
    }

    const { record } = props;
    const param = {
      paramIn: {
        list: [
          {
            id: record.id,
          },
        ],
        dockGid: selectedTask.dockGid,
        dockResourceLineGid: selectedTask.dockResourceLineGid,
        appointmentDate: selectedTask.appointmentDate,
      },

      macroCode: "TMS_SS_SUBMIT_APPOINTMENT",
    };

    const resp = await macroRequest(param);

    MacroNotification.open({
      ...resp,
      onSuccess: () => {
        // finally
        const { targetModal } = props;
        targetModal.close();
      },
      handleErrorClose: () => {},
    });
  };

  return (
    <>
      <ContentWrapper width='1200px'>
        <MainInfo>
          <div className='main-title'>
            <div className='main-tag'>{`${record.equipmentNumber || ""} (${
              record.shipmentXid
            })`}</div>
            <Tag color='blue'>{stopType}</Tag>
          </div>
        </MainInfo>
        <Form dataSet={formDs} columns={3}>
          <Output name='locationName' />
          <Output name='plannedArrival' />
          {/* ({ value, text, name, record, dataSet }) => ReactNode */}
          <Output
            renderer={({ record }) => {
              const totalItemCount = record.get("totalItemCount");
              const totalWeight = record.get("totalWeight");
              const totalVolume = record.get("totalVolume");
              return `总数量：${totalItemCount || ""}，总重量：${
                totalWeight || ""
              }，总体积：${totalVolume || ""}`;
            }}
          />
        </Form>

        <RailwayGantt
          ref={ganntRef}
          data={ganttData}
          setSelectedTask={setSelectedTask}
          queryGanttData={queryGanttData}
          minuteStep={minuteStep}
          setMinuteStep={setMinuteStep}
        />
      </ContentWrapper>
      <Footer>
        <div
          className='button cancel'
          onClick={() => {
            cancel();
          }}
        >
          取消
        </div>
        <div
          className='button confirm'
          onClick={() => {
            confirm();
          }}
        >
          确认
        </div>
      </Footer>
    </>
  );
};

export default App;
